﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//
using System.Windows.Forms;
using System.Drawing;
using System.IO;
//AForge摄像头
//using AForge;
using AForge.Video;
using AForge.Video.DirectShow;
using AForge.Imaging;
using AForge.Imaging.Filters;
//引用AForge.video.ffmpeg，打开时会报错：找不到指定的模块，需要把发行包第三方文件externals\ffmpeg\bin里的dll文件拷到windows的system32文件夹下。
using AForge.Video.FFMPEG;

namespace HRecycle
{

    #region //摄像头控制类，_camera
    /// <summary>
    /// 摄像头控制类，_camera，通过AForge控制，20160223
    ///   1：创建摄像头对象，createCameraObj
    ///   2：获取摄像头列表，让客户选择，getCameraList
    ///   3：启动摄像头，cameraStart
    ///   4：停止摄像头，cameraStop
    ///   5：拍照：getAPicture
    ///   6：录像：LuXiang=true
    /// 20160223，周承昊
    /// </summary>
    public partial class iCamera2015
    {   //摄像头类
        public string globalErrorMessage = "";                          //错误信息
        public AForge.Controls.VideoSourcePlayer videoPlayer = null;    //摄像头：预览窗口
        public FilterInfoCollection videoDevices = null;                //设备列表
        public VideoFileWriter videoWriter = null;                      //录像写入
        public ComboBox cbxCameraList = null;                           //摄像头列表


        #region //拍照，getAPicture
        /// <summary>
        /// 拍照当前帧
        /// </summary>
        /// <param name="bmp">返回取得的位图</param>
        /// <returns>成功返回0，错误信息记录在globalErrorMessage中</returns>
        public int getAPicture(ref Bitmap bmp) { return getAPicture(ref bmp, "", System.Drawing.Imaging.ImageFormat.Bmp); }
        public int getAPicture(ref Bitmap bmp, string sFile) { return getAPicture(ref bmp, sFile, System.Drawing.Imaging.ImageFormat.Jpeg); }
        public int getAPicture(ref Bitmap bmp, string sFile, System.Drawing.Imaging.ImageFormat AFormat)
        {
            int result = -1;
            try
            {
                if (!videoPlayer.IsRunning) { globalErrorMessage = "请启动摄像头"; return result; }

                //
                bmp = videoPlayer.GetCurrentVideoFrame();
                if (!string.IsNullOrEmpty(sFile))
                {
                    string s = System.IO.Path.GetDirectoryName(sFile);
                    if (!System.IO.Directory.Exists(s)) System.IO.Directory.CreateDirectory(s);
                    if (bmp != null) bmp.Save(s + "" + DateTime.Now.ToString("yyyyMMdd_HHmmsszzz") + ".jpg", AFormat);
                }
                //完成
                result = 0;
            }
            catch (Exception x)
            { globalErrorMessage = x.Message + " 错误来源：getAPicture"; }
            return result;
        }
        #endregion


        public void onVideoSourcePlayerNewFrame(object sender, ref Bitmap image)
        {   //录像
            //写到屏幕上的时间
            Graphics g = Graphics.FromImage(image);
            SolidBrush drawBrush = new SolidBrush(Color.Yellow);
            Font drawFont = new Font("Arial", 6, FontStyle.Bold, GraphicsUnit.Millimeter);
            int xPos = image.Width - (image.Width - 15), yPos = 10;
            string s = "", drawDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            g.DrawString(drawDate, drawFont, drawBrush, xPos, yPos);        //写到界面上

            //创建文件路径
            //fileFullPath = path + fileName;

            if (!LuXiang)
            {   //停止录像
                createNewFile = true;  //这里要设置为true表示要创建新文件
                if (videoWriter != null) videoWriter.Close();
            }
            else
            {   //开始录像
                if (createNewFile)
                {
                    //确认路径
                    if (string.IsNullOrEmpty(videoPath)) videoPath = System.IO.Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath);
                    else if (!Directory.Exists(videoPath)) Directory.CreateDirectory(videoPath);
                    if (videoPath.Substring(videoPath.Length - 1, 1) != "\\") videoPath += "\\";
                    //文件名
                    videoFileName = DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".avi";
                    videoFileFullPath = videoPath + videoFileName;
                    createNewFile = false;
                    if (videoWriter != null)
                    {
                        videoWriter.Close();
                        videoWriter.Dispose();
                    }
                    videoWriter = new VideoFileWriter();
                    //这里必须是全路径，否则会默认保存到程序运行根据录下了
                    //frameRate = (videoPlayer.VideoSource as VideoCaptureDevice).DesiredFrameRate;
                    videoWriter.Open(videoFileFullPath, image.Width, image.Height, frameRate, VideoCodec.MPEG4);
                    videoWriter.WriteVideoFrame(image);
                }
                else
                {
                    videoWriter.WriteVideoFrame(image);
                }
            }
        }
        private bool createNewFile = true;
        private string videoFileFullPath = "";
        /// <summary>
        /// 视频录像存放路径，录像视频文件名如果没有传入，会自动生成文件名，放在这个文件夹里
        /// </summary>
        public string videoPath = System.IO.Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath);
        //private List<string> videoPaths = new List<string>();
        /// <summary>
        /// 视频录像文件名，不包含文件夹，完整的路径是(videoPath+videoFileName)合起来的
        /// </summary>
        public string videoFileName = "";
        /// <summary>
        /// 是否录像，开启录像需要传入文件名，未传入的话自动生成一个文件名
        /// </summary>
        public bool LuXiang = false;
        /// <summary>
        /// 系统默认的帧率20
        /// </summary>
        public int frameRate = 10;                      //系统默认的帧率20，摄像头默认15


        #region //创建摄像头对象，createCameraViewer
        /// <summary>
        /// 创建摄像头查看的控件
        /// </summary>
        /// <param name="AParent">上级，一般是一个form</param>
        /// <param name="ALocation">位置</param>
        /// <param name="ASize">大小</param>
        /// <returns>成功返回0，错误信息记录在globalErrorMessage中</returns>
        public int createCameraViewer(Control AParent, Point ALocation, Size ASize)
        {   //创建摄像头对象
            int result = -1;
            try
            {
                if (videoPlayer != null) return 0;
                //
                videoPlayer = new AForge.Controls.VideoSourcePlayer();
                videoPlayer.Parent = AParent;
                if (ALocation == null) ALocation = new Point(20, 50);   //位置
                videoPlayer.Location = ALocation;
                if (ASize == null) ASize = new Size(325, 245);          //尺寸
                videoPlayer.Size = ASize;
                //videPlayer.Visible = true;

                //录像事件
                videoPlayer.NewFrame += new AForge.Controls.VideoSourcePlayer.NewFrameHandler(onVideoSourcePlayerNewFrame);

                //完成
                result = 0;
            }
            catch (Exception x)
            { globalErrorMessage = x.Message + " 错误来源：[createCameraObj]"; }
            return result;
        }
        #endregion


        #region //启动摄像头，cameraStart
        /// <summary>
        /// 启动摄像头
        /// </summary>
        /// <returns>成功返回0，错误信息记录在globalErrorMessage中</returns>
        public int cameraStart() { return cameraStart(""); }
        public int cameraStart(int cameraIndex) { return cameraStart(videoDevices[cameraIndex].MonikerString); }
        public int cameraStart(string deviceMoniker)
        {   //启动摄像头
            int result = -1;
            string s = deviceMoniker;
            try
            {
                if (string.IsNullOrEmpty(s) && cbxCameraList != null) s = videoDevices[cbxCameraList.SelectedIndex].MonikerString;
                VideoCaptureDevice videoSource = new VideoCaptureDevice(s);
                //videoSource.DesiredFrameSize = new Size(320, 240);
                //videoSource.DesiredFrameRate = 1;

                videoPlayer.VideoSource = videoSource;
                videoPlayer.Start();

                //完成
                result = 0;
            }
            catch (Exception x)
            { globalErrorMessage = x.Message + ""; }
            return result;
        }
        #endregion


        #region //停止摄像头，cameraStop
        /// <summary>
        /// 停止摄像头，在录像的话同时停止录像
        /// </summary>
        /// <returns>成功返回0，错误信息记录在globalErrorMessage中</returns>
        public int cameraStop()
        {   //停止摄像头
            int result = -1;
            try
            {
                if (videoWriter != null)
                {   //正在录像，停了
                    LuXiang = false;
                    videoWriter.Close();
                    videoWriter.Dispose();
                    videoWriter = null;
                }
                if (videoPlayer != null)
                {   //可以看，停了
                    videoPlayer.SignalToStop();
                    videoPlayer.WaitForStop();
                }
                //
                result = 0;
            }
            catch (Exception x)
            { globalErrorMessage = x.Message + " 错误来源：[cameraStop]"; }
            return result;
        }
        #endregion


        #region //获取摄像头清单，getCameraList
        /// <summary>
        /// 获取摄像头清单，有cbxCameraList控件的话会同时写入其Items
        /// </summary>
        /// <param name="cameras">返回的集合</param>
        /// <returns>成功返回0，错误信息记录在globalErrorMessage中</returns>
        public bool getCameraList(ref List<string> cameras)
        {
            bool result = false;
            try
            {
                // 枚举所有视频输入设备
                videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);

                if (videoDevices.Count == 0) throw new ApplicationException();

                //清单
                if (cbxCameraList != null) cbxCameraList.Items.Clear();
                cameras.Clear();
                foreach (FilterInfo device in videoDevices)
                {
                    if (cbxCameraList != null) cbxCameraList.Items.Add(device.Name);
                    cameras.Add(device.Name);
                }

                if (cbxCameraList != null) cbxCameraList.SelectedIndex = 0;
                //完成
                result = true;
            }
            catch (Exception x /*ApplicationException*/)
            {
                globalErrorMessage = x.Message + " 错误来源：[getCameraList]";
                if (cbxCameraList != null) cbxCameraList.Items.Add("没有摄像头");     //No local capture devices
                videoDevices = null;
            }
            return result;
        }
        #endregion

    }
    #endregion

}
